﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using common4gp;

namespace wpf4gp.Helpers
{

    /// <summary>
    /// Abstract class for use notification property changes
    /// </summary>
    public abstract class NotificationObject : INotifyPropertyChanged
    {

        /// <summary>
        /// Raise that a property is changed
        /// </summary>
        /// <typeparam name="T">Type of the action</typeparam>
        /// <param name="action">Property that is changed</param>
        protected void RaisePropertyChanged<T>(Expression<Func<T>> action)
        {
            Contract.Requires<ArgumentNullException>(action.IsNotNull());
            var propertyName = GetPropertyName(action);
            RaisePropertyChanged(propertyName);
        }

        /// <summary>
        /// Returns the name of the property of the action
        /// </summary>
        /// <typeparam name="T">Type of the action</typeparam>
        /// <param name="action">Property that is changed</param>
        /// <returns>Name of the action</returns>
        private static string GetPropertyName<T>(Expression<Func<T>> action)
        {
            Contract.Requires<ArgumentNullException>(action.IsNotNull());
            Contract.Ensures(Contract.Result<string>().IsNotNull());
            var expression = (MemberExpression)action.Body;
            var propertyName = expression.Member.Name;
            return propertyName;
        }

        /// <summary>
        /// Calls all handlers associated to the property
        /// </summary>
        /// <param name="propertyName">Name of the changed property</param>
        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged.IsNotNull())
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Event raised when a property changes
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
    }
}
